#include "documentcollection.h"

#include <QDir>
#include <QFile>
#include <qmath.h>

#include <QDebug>

DocumentCollection::DocumentCollection()
{
}

DocumentCollection::DocumentCollection(const QString &indexFile)
{
    QFile inFile(indexFile);
    QDataStream in(&inFile);
    if(inFile.open(QIODevice::ReadOnly)){
        in >> docNames;
        in >> *this;
        inFile.close();
    }
    else
        qCritical("Cannot open index file");
}

const Document &DocumentCollection::document(const QString &docName)
{
    return this->at(docNames.indexOf(docName));
}

void DocumentCollection::index(const QString &docDir, const QString &indexFile)
{
    QDir dir(docDir);
    QStringList files(dir.entryList(QDir::Files));
    int i = 1;

    QHash<QString, int> term_docNum;    // <term, number of documents with term>

    // read docs
    foreach(const QString &file, files){
        *this << Document(QString("%1/%2").arg(docDir).arg(file));
        docNames << this->last().name;
        const QStringList &terms = this->last().terms();
        for(QStringList::const_iterator term = terms.constBegin(); term != terms.constEnd(); term++)
            if(term_docNum.contains(*term))
                term_docNum[*term]++;
            else
                term_docNum.insert(*term, 1);
        qDebug() << QString("reading %1/%2").arg(i).arg(files.size());
        i++;
    }

    // calculate weights
    i = 1;
    for(DocumentCollection::iterator doc = begin(); doc != end(); doc++){
        for(QHash<QString, int>::const_iterator term_num = doc->content.constBegin(); term_num != doc->content.constEnd(); term_num++){
            const QString &term = term_num.key();
            doc->weights.insert(term, doc->tf(term) * qLn(double(size()) / term_docNum[term]));
        }
        qDebug() << QString("calculating weights %1/%2").arg(i).arg(size());
        i++;
    }

    // save index
    saveIndexToFile(indexFile);
}

void DocumentCollection::saveIndexToFile(const QString &file) const
{
    qDebug() << "saving index...";
    QFile outFile(file);
    QDataStream out(&outFile);
    outFile.open(QIODevice::WriteOnly);
    out << docNames;
    out << *this;
    outFile.close();
    qDebug() << "done";
}

QMultiMap<double, QString> DocumentCollection::findSimilar(const Document &doc)
{
    QMultiMap<double, QString> result;
    int counter = 0;
    for(DocumentCollection::const_iterator it = constBegin(); it != constEnd(); it++){
        result.insert(doc.similarityCos(*it), it->name);
        counter++;
    }
    return result;
}
